#include "Avalon/IO/PipedMessageWriter.hpp"
#include "Avalon/IO/Buffer.hpp"
#include "Avalon/IO/IOException.hpp"
#include "Avalon/IO/PipedMessageReader.hpp"

using namespace Avalon;
using namespace Avalon::IO;
using namespace Avalon::Threading;
using namespace boost;

PipedMessageWriter::PipedMessageWriter(PipedMessageReader* destination)
    : m_mutex(destination->m_mutex),
      m_destination(destination) {
  lock_guard<recursive_mutex> lock(*m_mutex);
  m_destination->Connect(this);
}

PipedMessageWriter::~PipedMessageWriter() {
  Break();
}

void PipedMessageWriter::Break() {
  lock_guard<recursive_mutex> lock(*m_mutex);
  if(m_destination == NULL) {
    return;
  }
  m_destination->InternalBreak();
  m_destination = NULL;
}

Async<void>::Ptr PipedMessageWriter::Write(const void* data, int size) {
  return Write(Buffer(data, size));
}

Async<void>::Ptr PipedMessageWriter::Write(const Buffer& data) {
  lock_guard<recursive_mutex> lock(*m_mutex);
  if(m_destination == NULL) {
    AsyncOwner<void>::Ptr result = AsyncOwner<void>::Create();
    result->SetException(IOException("Pipe broken."));
    return result;
  }
  m_destination->Write(data);
  return NewAsync();
}

void PipedMessageWriter::InternalBreak() {
  m_destination = NULL;
}
